package com.wx.pay.util;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Description: http请求工具类
 * @author kinfeng
 * @date 2015年12月10日 上午11:03:26 
 * @version V1.0
 */
public class HttpRequestUtil {
	private final static Logger logger = LoggerFactory.getLogger(HttpRequestUtil.class);
	public final static String METHOD_GET = "GET";
	public final static String METHOD_POST = "POST";
	/** 默认请求超时毫秒数 **/
	public final static int DEFAULT_TIMEOUT = 60000;
	
	/** 请求地址 **/
	private String url;
	/** 请求路径 **/
	private String path;
	/** 头**/
	private Map<String,String> heads;
	/** 参数**/
	private Map<String,String[]> params;
	/** 发送内容体 **/
	private String content;
	/** 请求超时毫秒数 **/
	private int timeout;
	/** 请求方法**/
	private String method;
	
	public HttpRequestUtil() {
		super();
	}
	
	/**
	 * @param url
	 */
	public HttpRequestUtil(String url) {
		super();
		this.url = url;
	}

	/**
	 * @param url
	 * @param params
	 */
	public HttpRequestUtil(String url, Map<String,String[]> params) {
		super();
		this.url = url;
		this.params = params;
	}
	
	/**
	 * @param url
	 * @param heads
	 * @param params
	 */
	public HttpRequestUtil(String url, Map<String,String> heads, Map<String,String[]> params) {
		super();
		this.url = url;
		this.heads = heads;
		this.params = params;
	}
	
	/**
	 * @param url
	 * @param heads
	 * @param content
	 */
	public HttpRequestUtil(String url, Map<String,String> heads, String content) {
		super();
		this.url = url;
		this.heads = heads;
		this.content = content;
	}
	
	/**
	 * @param url
	 * @param content
	 */
	public HttpRequestUtil(String url, String content) {
		super();
		this.url = url;
		this.content = content;
	}

	/**
	 * 发送post请求
	 * @return
	 */
	public String post(){
		setMethod(METHOD_POST);
		return request();
	}
	
	/**
	 * 发送get请求
	 * @return
	 */
	public String get(){
		setMethod(METHOD_GET);
		return request();
	}
	
	/**
	 * 发送http请求
	 * @return
	 */
	/*
	public String request(){
		HttpClient httpClient = new HttpClient();
		PostMethod method = new PostMethod(getUrl()+(getPath()==null?"":getPath()));
		try {
			httpClient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"utf-8");
			method.addRequestHeader("Content-type","application/json; charset=utf-8");  
			method.addRequestHeader("Accept", "application/json");
			loadHeads(method);
			loadParams(method);
			loadContent(method);
			httpClient.executeMethod(method);
			String result = method.getResponseBodyAsString();
			return result;
		} catch (Exception e) {
			throw new HttpRequestException(e);
		}finally{
			if(method!=null){
				method.releaseConnection();
			}
		}
	}*/
	
	/**
	 * 发送http请求
	 * @return
	 */
	public String request(){
		HttpURLConnection connection = null;
		try {
			connection = createHttpURLConnection();
			loadHeads(connection);
			loadParams(connection);
			loadContent(connection);
			connection.getOutputStream().close();
			if(connection.getResponseCode()==200){
				String result = StreamUtil.readString(connection.getInputStream());
				logger.debug("read content:");
				logger.debug(result);
				return result;
			}else{
				String errorInfo = StreamUtil.readString(connection.getErrorStream());
				throw new RuntimeException( errorInfo);
			}
		} catch (RuntimeException e) {
			throw e;
		}catch (Exception e) {
			throw new RuntimeException(e);
		}finally{
			if(connection!=null){
				connection.disconnect();
			}
		}
	}
	
	/**
	 * 加载head参数
	 * @param connection
	 */
	private void loadHeads(HttpURLConnection connection){
		if(heads!=null){
			for(Entry<String, String> row : heads.entrySet()){
				logger.debug("setRequestProperty:"+row.getKey()+"="+row.getValue());
				connection.setRequestProperty(row.getKey(), row.getValue());
			}
		}
	}
	
	/**
	 * 加载head参数
	 * @param connection
	 */
	private void loadHeads(PostMethod method){
		if(heads!=null){
			for(Entry<String, String> row : heads.entrySet()){
				logger.debug("setRequestProperty:"+row.getKey()+"="+row.getValue());
				method.addRequestHeader(row.getKey(), row.getValue());
			}
		}
	}
	
	/**
	 * 加载参数
	 * @param connection
	 * @throws IOException 
	 */
	private void loadParams(HttpURLConnection connection) throws IOException{
		if(params!=null){
			StringBuffer temp = new StringBuffer();
			for(Entry<String, String[]> row : params.entrySet()){
				for(String val : row.getValue()){
					temp.append("&").append(row.getKey()).append("=").append(URLDecoder.decode(val, "UTF-8"));
				}
			}
			String params = temp.toString();
			logger.debug("output params:");
			logger.debug(params);
			byte[] data = params.getBytes("UTF-8");
			connection.setRequestProperty("Content-Length", String.valueOf(data));
			connection.getOutputStream().write(data);
		}
	}
	
	/**
	 * 加载参数
	 * @param connection
	 * @throws IOException 
	 */
	private void loadParams(PostMethod method) throws IOException{
		if(params!=null){
			StringBuffer temp = new StringBuffer();
			NameValuePair[] parametersBody = new NameValuePair[params.size()];
			int i = 0;
			for(Entry<String, String[]> row : params.entrySet()){
				if(row.getValue()==null){
					parametersBody[i++] =  new NameValuePair(row.getKey(), null);
				}else{
					for(String value : row.getValue()){
						parametersBody[i++] =  new NameValuePair(row.getKey(), value);
						logger.debug("add params:"+row.getKey()+"="+value);
					}
				}
			}
			method.setRequestBody(parametersBody);
		}
	}
	
	
	
	/**
	 * 加载报文
	 * @param connection
	 * @throws IOException
	 */
	private void loadContent(HttpURLConnection connection) throws IOException{
		if(content!=null){
			if(!METHOD_POST.equals(connection.getRequestMethod())){
				throw new RuntimeException("GET不能发送content");
			}
			logger.debug("output content:");
			logger.debug(content);
			byte[] data = content.getBytes("UTF-8");
			connection.setRequestProperty("Content-Length", String.valueOf(data));
			connection.getOutputStream().write(data);
		}
	}
	
	/**
	 * 加载报文
	 * @param connection
	 * @throws IOException
	 */
	private void loadContent(PostMethod method) throws IOException{
		if(content!=null){
			if(!METHOD_POST.equals(getMethod())){
				throw new RuntimeException("GET不能发送content");
			}
			logger.debug("output content:");
			logger.debug(content);
			method.setRequestBody(content);
		}
	}
	
	/**
	 * 创建http请求连接对象
	 * @return
	 * @throws IOException
	 */
	private HttpURLConnection createHttpURLConnection() throws IOException{
		URL urlObj = new URL(getUrl()+(getPath()==null?"":getPath()));
		HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection();
		logger.debug("request url:");
		logger.debug(urlObj.toString());
		//connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded;charset=UTF-8");
		connection.setRequestProperty("Accept-Charset", "utf-8");
		connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
		connection.setDoInput(true);
		connection.setDoOutput(true);
		connection.setConnectTimeout(timeout<1 ? DEFAULT_TIMEOUT : timeout);
		connection.setRequestMethod(method==null?METHOD_GET:method);
		return connection;
	}
	
	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public String getMethod() {
		return method;
	}

	public void setMethod(String method) {
		this.method = method;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public Map<String, String> getHeads() {
		return heads;
	}

	public void setHeads(Map<String, String> heads) {
		this.heads = heads;
	}

	public Map<String, String[]> getParams() {
		return params;
	}

	public void setParams(Map<String, String[]> params) {
		this.params = params;
	}

	public int getTimeout() {
		return timeout;
	}

	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}
	
	
	
}
